package com.analysis.services;

import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.alibaba.fastjson2.JSONObject;
import com.analysis.client.*;
import com.analysis.config.CommonConstant;
import com.analysis.dto.*;
import com.analysis.enums.ModelChatClientEnum;
import com.analysis.utils.ParseTextUtils;
import jakarta.annotation.PreDestroy;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

/**
 * 品牌曝光量分析服务
 */
@Service
public class BrandExposureAnalysisService {

    private static final Logger logger = LoggerFactory.getLogger(BrandExposureAnalysisService.class);
    private static final Logger aiModelLogger = LoggerFactory.getLogger("com.analysis.client");

    @Autowired
    private BrandExposureAiChatClient brandExposureAiChatClient;
    @Autowired
    private BaiduAgentAiChatClient baiduAgentAiChatClient;
    @Autowired
    private TencentAgentAIChatClient tencentAgentAIChatClient;
    @Autowired
    private DoubaoAgentAiChatClient doubaoAgentAiChatClient;
    @Autowired
    private DeepseekAIChatClient deepseekAIChatClient;
    @Autowired
    private KimiAIChatClient kimiAIChatClient;

    // Java 17优化的线程池配置：核心线程50，最大线程100
    private final ExecutorService executorService = createOptimizedThreadPool();

    // DeepSeek 并行调用配置
    private static final int DEEPSEEK_TIMEOUT_MINUTES = 5;
    private static final int REFERENCE_TIMEOUT_MINUTES = 3;

    /**
     * 创建Java 17优化的线程池
     */
    private ExecutorService createOptimizedThreadPool() {
        // 自定义线程工厂，提供有意义的线程名称
        ThreadFactory threadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final String namePrefix = "ai-analysis-";

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
                // Java 17优化：设置线程优先级和守护线程状态
                t.setPriority(Thread.NORM_PRIORITY);
                t.setDaemon(false);
                return t;
            }
        };

        return new ThreadPoolExecutor(
                100, // 核心线程数
                300, // 最大线程数
                60L, // 空闲线程存活时间
                TimeUnit.SECONDS, // 时间单位
                new LinkedBlockingQueue<>(1000), // 工作队列
                threadFactory, // 自定义线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略：调用者运行
        );
    }

    /**
     * 获取可用的AI模型列表
     *
     * @param aiModels 指定的AI模型列表，如果为null或空则使用所有可用模型
     * @return 可用的AI模型数组
     */
    private String[] getAvailableModels(List<String> aiModels) {
        if (aiModels != null && !aiModels.isEmpty()) {
            // 验证指定的模型是否可用
            List<String> validModels = aiModels.stream()
                    .filter(model -> {
                        if (brandExposureAiChatClient.isSourceAvailable(model)) {
                            return true;
                        } else {
                            logger.warn("指定的AI模型 '{}' 不可用，已跳过", model);
                            return false;
                        }
                    })
                    .toList();

            if (validModels.isEmpty()) {
                logger.error("没有可用的AI模型");
                throw new RuntimeException("没有可用的AI模型");
            }

            String[] availableModels = validModels.toArray(new String[0]);
            logger.info("最终使用 {} 个AI模型: {}", availableModels.length, Arrays.toString(availableModels));
            return availableModels;
        } else {
            // 如果没有指定模型，则使用所有可用模型
            String[] availableModels = brandExposureAiChatClient.getAvailableSources();
            logger.info("使用所有可用AI模型: {}", Arrays.toString(availableModels));
            return availableModels;
        }
    }

    /**
     * 分析品牌曝光量
     * <p>
     * 该方法负责协调整个品牌曝光量分析流程，包括：
     * 1. 参数验证和预处理
     * 2. 竞品名称解析
     * 3. 品牌列表构建
     * 4. AI模型并发调用
     * 5. 曝光量分析和结果构建
     *
     * @param ownProductName  自有产品名称
     * @param competitorNames 竞品名称（逗号分隔）
     * @param questions       问题列表
     * @param aiModels        指定的AI模型列表（可选）
     * @return 品牌曝光量分析结果
     * @throws IllegalArgumentException 当参数无效时
     * @throws RuntimeException         当分析过程中发生错误时
     */
    public BrandExposureResponse analyzeBrandExposure(String ownProductName, String competitorNames,
                                                      List<String> questions, List<String> aiModels) {
        // 参数验证
        validateInputParameters(ownProductName, questions);
        long startTime = System.currentTimeMillis();
        try {
            // 1. 预处理：解析竞品和构建品牌列表
            AnalysisContext context = preprocessAnalysisData(ownProductName, competitorNames, questions, aiModels);

            // 2. 并发调用AI模型
            Map<String, Map<String, BrandExposureAiCallDTO>> modelAnswers = callAllModelsConcurrently(
                    context.getAllBrandList(), questions, context.getAvailableModels());

            // 3. 分析曝光量并构建响应
            return buildAnalysisResponse(context, modelAnswers);
        } catch (IllegalArgumentException e) {
            logger.error("参数验证失败 -  产品: {}, 竞品: {}, 错误: {}", ownProductName, competitorNames, e.getMessage());
            throw e;
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            logger.error("分析品牌曝光量失败 -耗时: {}ms, 产品: {}, 竞品: {}, 错误: {}", duration, ownProductName, competitorNames, e.getMessage(), e);
            throw new RuntimeException("分析品牌曝光量失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成分析ID用于追踪
     *
     * @return 分析ID
     */
    private String generateAnalysisId() {
        return "ANALYSIS_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
    }

    /**
     * 预处理分析数据
     *
     * @param ownProductName  自有产品名称
     * @param competitorNames 竞品名称（逗号分隔）
     * @param questions       问题列表
     * @param aiModels        指定的AI模型列表
     * @return 分析上下文
     */
    private AnalysisContext preprocessAnalysisData(String ownProductName, String competitorNames,
                                                   List<String> questions, List<String> aiModels) {
        // 1. 解析竞品名称列表
        List<String> competitorList = parseCompetitorNames(competitorNames);

        // 2. 构建所有品牌列表
        List<String> allBrandList = buildAllBrandList(ownProductName, competitorList);

        return new AnalysisContext(ownProductName, competitorList, allBrandList,
                aiModels, questions);
    }

    /**
     * 构建分析响应
     *
     * @param context      分析上下文
     * @param modelAnswers AI模型回答结果
     * @return 品牌曝光量分析响应
     */
    private BrandExposureResponse buildAnalysisResponse(AnalysisContext context,
                                                        Map<String, Map<String, BrandExposureAiCallDTO>> modelAnswers) {
        return analyzeExposure(context.getOwnProductName(), context.getCompetitorList(),
                context.getQuestions(), modelAnswers, context.getAvailableModels());
    }

    /**
     * 分析上下文内部类
     * 用于封装分析过程中的上下文数据
     */
    private static class AnalysisContext {
        private final String ownProductName;
        private final List<String> competitorList;
        private final List<String> allBrandList;
        private final List<String> availableModels;
        private final List<String> questions;

        public AnalysisContext(String ownProductName, List<String> competitorList,
                               List<String> allBrandList, List<String> availableModels,
                               List<String> questions) {
            this.ownProductName = ownProductName;
            this.competitorList = competitorList;
            this.allBrandList = allBrandList;
            this.availableModels = availableModels;
            this.questions = questions;
        }

        // Getters
        public String getOwnProductName() {
            return ownProductName;
        }

        public List<String> getCompetitorList() {
            return competitorList;
        }

        public List<String> getAllBrandList() {
            return allBrandList;
        }

        public List<String> getAvailableModels() {
            return availableModels;
        }

        public List<String> getQuestions() {
            return questions;
        }
    }

    /**
     * 验证输入参数
     *
     * @param ownProductName 自有产品名称
     * @param questions      问题列表
     * @throws IllegalArgumentException 当参数无效时
     */
    private void validateInputParameters(String ownProductName, List<String> questions) {
        if (StringUtils.isBlank(ownProductName)) {
            throw new IllegalArgumentException("自有产品名称不能为空");
        }
        if (questions == null || questions.isEmpty()) {
            throw new IllegalArgumentException("问题列表不能为空");
        }
    }

    /**
     * 解析竞品名称列表
     *
     * @param competitorNames 竞品名称（逗号分隔）
     * @return 竞品名称列表
     */
    private List<String> parseCompetitorNames(String competitorNames) {
        if (StringUtils.isBlank(competitorNames)) {
            return List.of();
        }
        List<String> competitorList = Arrays.stream(competitorNames.split(","))
                .map(String::trim)
                .filter(StringUtils::isNotBlank)
                .distinct() // 去重
                .toList();
        return competitorList;
    }

    /**
     * 构建所有品牌列表
     *
     * @param ownProductName 自有产品名称
     * @param competitorList 竞品列表
     * @return 所有品牌列表
     */
    private List<String> buildAllBrandList(String ownProductName, List<String> competitorList) {
        List<String> allBrandList = Stream.concat(
                        Stream.of(ownProductName.trim()),
                        competitorList.stream()
                ).distinct() // 去重
                .toList();
        return allBrandList;
    }

    /**
     * 并发调用所有AI模型回答问题
     * <p>
     * 该方法使用线程池并发调用多个AI模型，每个模型和问题的组合都有独立的线程处理。
     * 使用CompletableFuture实现异步处理，提高整体性能。
     *
     * @param allBrandList 所有品牌列表
     * @param questions    问题列表
     * @param aiModels     AI模型列表
     * @return 模型回答结果映射，结构为 Map<问题, Map<模型, 回答DTO>>
     */
    private Map<String, Map<String, BrandExposureAiCallDTO>> callAllModelsConcurrently(
            List<String> allBrandList, List<String> questions, List<String> aiModels) {
        Map<String, Map<String, BrandExposureAiCallDTO>> modelAnswers = new ConcurrentHashMap<>();
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        // 计算总任务数
        int totalTasks = questions.size() * aiModels.size();

        // 为每个问题-模型组合创建异步任务
        for (String question : questions) {
            for (String model : aiModels) {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    processQuestionModelTask(question, model, allBrandList, modelAnswers);
                }, executorService);
                futures.add(future);
            }
        }

        // 等待所有任务完成，设置超时时间
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                    .get(600, TimeUnit.SECONDS); // 10分钟超时
        } catch (TimeoutException e) {
            logger.error("AI模型调用超时 - 总任务数: {}, 超时时间: 10分钟", totalTasks);
            throw new RuntimeException("AI模型调用超时", e);
        } catch (Exception e) {
            logger.error("等待AI模型调用任务完成时发生异常 - 总任务数: {}", totalTasks, e);
            throw new RuntimeException("AI模型调用失败", e);
        }
        return modelAnswers;
    }

    /**
     * 处理单个问题-模型任务
     *
     * @param question     问题内容
     * @param model        模型名称
     * @param allBrandList 所有品牌列表
     * @param modelAnswers 结果存储映射
     */
    private void processQuestionModelTask(String question, String model, List<String> allBrandList,
                                          Map<String, Map<String, BrandExposureAiCallDTO>> modelAnswers) {
        String taskId = "TASK_" + model + "_" + question.hashCode();
        long startTime = System.currentTimeMillis();

        try {
            // 第一步：调用AI模型获取答案
            AiCallResponse aiCallResponse = callQuestion(model, question);
            // 构建结果DTO
            BrandExposureAiCallDTO dto = new BrandExposureAiCallDTO();
            dto.setAnswerList(aiCallResponse.getContents());
            dto.setText(aiCallResponse.getText());
            dto.setReferences(aiCallResponse.getReferences());

            if (aiCallResponse.getContents() != null && !aiCallResponse.getContents().isEmpty()) {
                // 第二步：进行品牌分析
                List<String> aiBrandList = brandAnalysis(aiCallResponse.getContents(), allBrandList);
                dto.setBrandList(aiBrandList);
                // 线程安全地存储结果
                modelAnswers.computeIfAbsent(question, k -> new ConcurrentHashMap<>())
                        .put(model, dto);
            } else {
                // 创建空结果
                modelAnswers.computeIfAbsent(question, k -> new ConcurrentHashMap<>())
                        .put(model, dto);
            }
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.error("任务执行失败 - 任务ID: {}, 耗时: {}ms, 模型: {}, 问题: {}, 错误: {}",
                    taskId, duration, model, question, e.getMessage(), e);
            // 创建空结果，避免整个流程失败
            modelAnswers.computeIfAbsent(question, k -> new ConcurrentHashMap<>())
                    .put(model, new BrandExposureAiCallDTO());
        }
    }

    /**
     * 第一步：输入问题，让AI返回5个答案
     *
     * @param modelSource AI模型源
     * @param question    问题内容
     * @return 答案列表，如果失败返回空列表
     */
    private AiCallResponse callQuestion(String modelSource, String question) {
        long startTime = System.currentTimeMillis();
        try {
            // 特殊模型使用专用客户端
            if (ModelChatClientEnum.BAIDU.getSource().equals(modelSource)) {
                return callBaiduModel(question);
            }
            if (ModelChatClientEnum.YUANBAO.getSource().equals(modelSource)) {
                return callYuanbaoModel(question);
            }
            if (ModelChatClientEnum.DOUBAO.getSource().equals(modelSource)) {
                return callDoubaoModel(question);
            }
            if (ModelChatClientEnum.DEEPSEEK.getSource().equals(modelSource)) {
                return callDeepseekModel(question);
            }
            // 其他模型使用通用客户端
            return callGenericModel(modelSource, question, startTime);
        } catch (Exception e) {
            aiModelLogger.error("调用AI模型最终失败 - 耗时: {}ms, 模型: {}, 问题: {}, 错误: {}",
                    System.currentTimeMillis() - startTime, modelSource, question, e.getMessage(), e);
            return new AiCallResponse();
        }
    }

//    /**
//     * 调用百度模型（高可用并行版本）
//     * 使用线程池并行执行 callQuestion 和 callReference，提高响应速度和可用性
//     */
//    public AiCallResponse callBaiduModel(String question) {
//        long startTime = System.currentTimeMillis();
//        logger.info("开始调用百度模型 - 问题: {}", question);
//
//        int maxRetries = 2;
//        for (int attempt = 1; attempt <= maxRetries; attempt++) {
//            try {
//                // 创建并行任务
//                CompletableFuture<AiCallResponse> questionFuture = CompletableFuture.supplyAsync(() -> {
//                    try {
//                        return baiduAgentAiChatClient.callQuestion(question);
//                    } catch (Exception e) {
//                        aiModelLogger.error("百度 callQuestion 执行失败", e);
//                        throw new RuntimeException("百度 callQuestion 调用失败", e);
//                    }
//                }, executorService).orTimeout(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);
//
//                CompletableFuture<List<Reference>> referenceFuture = CompletableFuture.supplyAsync(() -> {
//                    try {
//                        return baiduAgentAiChatClient.callReference(question);
//                    } catch (Exception e) {
//                        aiModelLogger.error("百度 callReference 执行失败", e);
//                        return new ArrayList<Reference>();
//                    }
//                }, executorService).orTimeout(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);
//
//                // 等待两个任务完成
//                CompletableFuture<Void> allTasks = CompletableFuture.allOf(questionFuture, referenceFuture);
//                allTasks.get(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);
//
//                // 获取结果
//                AiCallResponse aiCallResponse = questionFuture.get();
//                List<Reference> references = referenceFuture.get();
//
//                // 构建响应
//                if (aiCallResponse != null) {
//                    aiCallResponse.setContents(ParseTextUtils.parseCommonText(aiCallResponse.getText()));
//                }
//                if (references != null && !references.isEmpty()) {
//                    aiCallResponse.setReferences(references);
//                }
//
//                long duration = System.currentTimeMillis() - startTime;
//                logger.info("百度模型调用完成 - 耗时: {}ms, 问题长度: {}, 答案数量: {}, 参考数量: {}",
//                        duration, question.length(),
//                        aiCallResponse.getContents() != null ? aiCallResponse.getContents().size() : 0,
//                        references != null ? references.size() : 0);
//
//                return aiCallResponse;
//            } catch (TimeoutException e) {
//                long duration = System.currentTimeMillis() - startTime;
//                aiModelLogger.warn("第{}次百度模型并行调用超时 - 耗时: {}ms, 问题: {}", attempt, duration, question, e);
//                if (attempt < maxRetries) {
//                    try {
//                        Thread.sleep(1000L * attempt);
//                    } catch (InterruptedException ie) {
//                        Thread.currentThread().interrupt();
//                        throw new RuntimeException("百度模型重试被中断", ie);
//                    }
//                }
//            } catch (Exception e) {
//                long duration = System.currentTimeMillis() - startTime;
//                aiModelLogger.warn("第{}次百度模型并行调用失败 - 耗时: {}ms, 问题: {}, 错误: {}",
//                        attempt, duration, question, e.getMessage());
//                if (attempt < maxRetries) {
//                    try {
//                        Thread.sleep(1000L * attempt);
//                    } catch (InterruptedException ie) {
//                        Thread.currentThread().interrupt();
//                        throw new RuntimeException("百度模型重试被中断", ie);
//                    }
//                }
//            }
//        }
//        // 所有重试都失败，返回空响应
//        long duration = System.currentTimeMillis() - startTime;
//        aiModelLogger.error("百度模型并行调用最终失败 - 耗时: {}ms, 问题: {}", duration, question);
//        return new AiCallResponse();
//    }

    /**
     * 调用百度模型（同步版本 - 备用方案）
     * 当并行版本出现问题时，可以回退到同步执行
     */
    public AiCallResponse callBaiduModel(String question) {
        long startTime = System.currentTimeMillis();
        aiModelLogger.info("开始同步调用百度模型 - 问题: {}", question);
        AiCallResponse aiCallResponse = new AiCallResponse();
        try {
            // 同步执行
            aiCallResponse = baiduAgentAiChatClient.callQuestion(question);
            if (aiCallResponse.getText() != null) {
                aiCallResponse.setContents(ParseTextUtils.parseCommonText(aiCallResponse.getText()));
            }
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.warn("第{}次百度模型同步调用失败 - 耗时: {}ms, 问题: {}, 错误: {}",
                    1, duration, question, e.getMessage());
        }
        return aiCallResponse;
    }

    /**
     * 调用元宝模型（腾讯）
     */
    public AiCallResponse callYuanbaoModel(String question) {
        long startTime = System.currentTimeMillis();
        int maxRetries = 2;
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                return tencentAgentAIChatClient.callQuesion(question);
            } catch (Exception e) {
                long duration = System.currentTimeMillis() - startTime;
                logger.warn("第{}次元宝模型调用失败 - 耗时: {}ms, 错误: {}", attempt, duration, e.getMessage());
                if (attempt < maxRetries) {
                    try {
                        Thread.sleep(1000L * attempt);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("元宝模型重试被中断", ie);
                    }
                }
            }
        }
        return new AiCallResponse();
    }

    /**
     * 调用豆包模型
     */
    public AiCallResponse callDoubaoModel(String question) {
        long startTime = System.currentTimeMillis();
        int maxRetries = 2;
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                return doubaoAgentAiChatClient.callQuesion(question);
            } catch (Exception e) {
                long duration = System.currentTimeMillis() - startTime;
                logger.warn("第{}次豆包模型调用失败 - 耗时: {}ms, 错误: {}", attempt, duration, e.getMessage());
                if (attempt < maxRetries) {
                    try {
                        Thread.sleep(1000L * attempt);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("豆包模型重试被中断", ie);
                    }
                }
            }
        }
        return new AiCallResponse();
    }

    /**
     * 调用 DeepSeek 模型（高可用并行版本）
     * 使用线程池并行执行 callQuestion 和 calReference，提高响应速度和可用性
     */
    public AiCallResponse callDeepseekModel(String question) {
        long startTime = System.currentTimeMillis();
        try {
            // 创建并行任务
            CompletableFuture<AiCallResponse> questionFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    return deepseekAIChatClient.callQuestion(question);
                } catch (Exception e) {
                    aiModelLogger.error("callQuestion 执行失败", e);
                    throw new RuntimeException("DeepSeek callQuestion 调用失败", e);
                }
            }, executorService).orTimeout(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);

            CompletableFuture<List<Reference>> referenceFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    return deepseekAIChatClient.calReference(question);
                } catch (Exception e) {
                    aiModelLogger.error("calReference 执行失败", e);
                    return new ArrayList<Reference>();
                }
            }, executorService).orTimeout(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);

            // 等待两个任务完成，设置超时时间
            CompletableFuture<Void> allTasks = CompletableFuture.allOf(questionFuture, referenceFuture);
            allTasks.get(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);

            // 获取结果
            AiCallResponse aiCallResponse = questionFuture.get();
            List<Reference> references = referenceFuture.get();

            // 设置参考信息
            aiCallResponse.setReferences(references);

            return aiCallResponse;
        } catch (TimeoutException e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.error("DeepSeek 并行调用超时 - 耗时: {}ms, 问题: {}", duration, question, e);
            throw new RuntimeException("DeepSeek 模型调用超时", e);
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.error("DeepSeek 并行调用失败 - 耗时: {}ms, 问题: {}", duration, question, e);
            throw new RuntimeException("DeepSeek 模型调用失败", e);
        }
    }

    /**
     * 调用 Kimi 模型（高可用并行版本）
     * 使用线程池并行执行 webSearch 和 参考信息抽取，提高响应速度和可用性
     */
    public AiCallResponse callKimiModel(String question) {
        long startTime = System.currentTimeMillis();
        logger.info("开始调用Kimi模型 - 问题: {}", question);

        try {
            // 创建并行任务：答案
            CompletableFuture<AiCallResponse> questionFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    aiModelLogger.debug("开始执行 Kimi webSearch 任务");
                    return kimiAIChatClient.webSearch(question);
                } catch (Exception e) {
                    aiModelLogger.error("Kimi webSearch 执行失败", e);
                    throw new RuntimeException("Kimi webSearch 调用失败", e);
                }
            }, executorService).orTimeout(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);

            // 创建并行任务：参考信息
            CompletableFuture<List<Reference>> referenceFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    aiModelLogger.debug("开始执行 Kimi 参考信息解析 任务");
                    // 通过二次请求让Kimi列出参考信息
                    String refPrompt = "列出你为回答“" + question + "”所提供的内容所参考和引用的信息源, 返回信息源的title和url";
                    AiCallResponse refResp = kimiAIChatClient.webSearch(refPrompt);
                    String refText = refResp != null ? refResp.getText() : null;
                    List<Reference> refs = ParseTextUtils.parseReferences(refText);
                    return refs != null ? refs : new ArrayList<Reference>();
                } catch (Exception e) {
                    aiModelLogger.error("Kimi 参考信息解析 执行失败", e);
                    return new ArrayList<Reference>();
                }
            }, executorService).orTimeout(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);

            // 等待两个任务完成，设置超时时间
            CompletableFuture<Void> allTasks = CompletableFuture.allOf(questionFuture, referenceFuture);
            allTasks.get(DEEPSEEK_TIMEOUT_MINUTES, TimeUnit.MINUTES);

            // 获取结果
            AiCallResponse aiCallResponse = questionFuture.get();
            List<Reference> references = referenceFuture.get();

            // 设置参考信息
            if (aiCallResponse != null) {
                aiCallResponse.setReferences(references);
            }

            long duration = System.currentTimeMillis() - startTime;
            logger.info("Kimi模型调用完成 - 耗时: {}ms, 问题长度: {}, 答案数量: {}, 参考数量: {}",
                    duration, question.length(),
                    aiCallResponse != null && aiCallResponse.getContents() != null ? aiCallResponse.getContents().size() : 0,
                    references != null ? references.size() : 0);
            return aiCallResponse;
        } catch (TimeoutException e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.error("Kimi 并行调用超时 - 耗时: {}ms, 问题: {}", duration, question, e);
            throw new RuntimeException("Kimi 模型调用超时", e);
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.error("Kimi 并行调用失败 - 耗时: {}ms, 问题: {}", duration, question, e);
            throw new RuntimeException("Kimi 模型调用失败", e);
        }
    }


    /**
     * 调用 DeepSeek 模型（同步版本 - 备用方案）
     * 当并行版本出现问题时，可以回退到同步执行
     */
    public AiCallResponse callDeepseekModelSync(String question) {
        long startTime = System.currentTimeMillis();
        aiModelLogger.info("开始同步调用 DeepSeek 模型 - 问题: {}", question);

        try {
            // 同步执行
            AiCallResponse aiCallResponse = deepseekAIChatClient.callQuestion(question);
            List<Reference> references = deepseekAIChatClient.calReference(question);
            aiCallResponse.setReferences(references);
            long duration = System.currentTimeMillis() - startTime;
            logger.info("DeepSeek 同步调用完成 - 耗时: {}ms, 问题长度: {}, 参考数量: {}",
                    duration, question.length(), references.size());
            return aiCallResponse;
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.error("DeepSeek 同步调用失败 - 耗时: {}ms, 问题: {}", duration, question, e);
            throw new RuntimeException("DeepSeek 同步调用失败", e);
        }
    }

    /**
     * 调用通用模型（Spring AI ChatClient）
     */
    public AiCallResponse callGenericModel(String modelSource, String promptText, long startTime) {
        ChatClient chatClient = brandExposureAiChatClient.getChatClient(modelSource);
        try {
            AiCallResponse aiCallResponse = tryContentMethod(chatClient, promptText, modelSource, startTime);
            if (aiCallResponse.getContents() != null) {
                return aiCallResponse;
            }
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            logger.warn("通用模型尝试失败 - 模型: {}, 耗时: {}ms, 错误: {}", modelSource, duration, e.getMessage());
        }
        return new AiCallResponse();
    }

    /**
     * 尝试使用 entity 方法
     */
    private AiCallResponse tryEntityMethod(ChatClient chatClient, String promptText, String modelSource, long startTime) {
        AiCallResponse aiCallResponse = new AiCallResponse();
        long id = System.currentTimeMillis();
        try {
            AiCallData aiCallData = chatClient.prompt()
                    .user(promptText + "，推荐5个")
//                    .advisors(
//                            a -> a
//                                    .param(CHAT_MEMORY_CONVERSATION_ID_KEY, id)  // 记忆用户Id
//                                    .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 3) // 总共记录100次
//                    )
                    .call()
                    .entity(AiCallData.class);
            aiCallResponse.setContents(aiCallData.getContents());
        } catch (Exception e) {
            aiModelLogger.warn("查询基础问题方法失败 - 模型: {}, 错误: {}", modelSource, e.getMessage());
        }

        try {
            AiReferenceData referenceData = chatClient
                    .prompt()
                    .user("列出你为回答“" + promptText + "”所提供的内容所参考和引用的信息源, 返回信息源的title和url")
//                    .advisors(
//                            a -> a
//                                    .param(CHAT_MEMORY_CONVERSATION_ID_KEY, id)  // 记忆用户Id
//                                    .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 3) // 总共记录2次
//                    )
                    .call()
                    .entity(AiReferenceData.class);
            if (referenceData != null) {
                List<Reference> references = new ArrayList<>();
                for (AiReferenceDetail referenceDetail : referenceData.getReference()) {
                    Reference reference = new Reference();
                    reference.setName(referenceDetail.getTitle());
                    reference.setUrl(referenceDetail.getUrl());
                    references.add(reference);
                }
                aiCallResponse.setReferences(references);
            }
        } catch (Exception e) {
            aiModelLogger.warn("查询信息源方法失败 - 模型: {}, 错误: {}", modelSource, e.getMessage());
        }
        return aiCallResponse;
    }

    /**
     * 尝试使用 content 方法 + 手动解析
     */
    private AiCallResponse tryContentMethod(ChatClient chatClient, String promptText, String modelSource, long startTime) {
        AiCallResponse aiCallResponse = new AiCallResponse();
        try {
            ChatResponse chatResponse = chatClient.prompt()
                    .user(promptText + CommonConstant.QUESTION_SIZE)
                    .call()
                    .chatResponse();

            // 解析数据
            if (chatResponse != null) {
                String content = chatResponse.getResult().getOutput().getText();
                aiCallResponse.setContents(ParseTextUtils.parseCommonText(content));
                aiCallResponse.setText(content);
                System.err.println(modelSource + "消耗token:" + chatResponse.getMetadata().getUsage().getTotalTokens());
            }
        } catch (Exception e) {
            aiModelLogger.error("Content方法失败 - 模型: {}, 错误: {}", modelSource, e.getMessage());
        }


        try {
            ChatResponse chatResponse = chatClient.prompt()
                    .user("列出你为回答“" + promptText + "”所提供的内容所参考和引用的信息源, 返回信息源的title和url")
                    .call()
                    .chatResponse();

            // 解析数据
            if (chatResponse != null) {
                String content = chatResponse.getResult().getOutput().getText();
                aiCallResponse.setReferences(ParseTextUtils.parseReferences(content));
                System.err.println(modelSource + "消耗token:" + chatResponse.getMetadata().getUsage().getTotalTokens());
            }
        } catch (Exception e) {
            aiModelLogger.error("查询信息源方法失败 - 模型: {}, 错误: {}", modelSource, e.getMessage());
        }

//        try {
//            AiReferenceData referenceData = chatClient
//                    .prompt()
//                    .user("列出你为回答“" + promptText + "”所提供的内容所参考和引用的信息源, 返回信息源的title和url")
//                    .call()
//                    .entity(AiReferenceData.class);
//            if (referenceData != null) {
//                List<Reference> references = new ArrayList<>();
//                for (AiReferenceDetail referenceDetail : referenceData.getReference()) {
//                    Reference reference = new Reference();
//                    reference.setName(referenceDetail.getTitle());
//                    reference.setUrl(referenceDetail.getUrl());
//                    references.add(reference);
//                }
//                aiCallResponse.setReferences(references);
//            }
//        } catch (Exception e) {
//            aiModelLogger.warn("查询信息源方法失败 - 模型: {}, 错误: {}", modelSource, e.getMessage());
//        }
        return aiCallResponse;
    }

    /**
     * 第二步：品牌分析：分析答案列表数据分别属于什么品牌
     *
     * @param answerList 待分析的答案列表
     * @param brandList  参考品牌列表
     * @return 品牌归属分析结果
     */
    private List<String> brandAnalysis(List<String> answerList, List<String> brandList) {
        // 参数验证
        if (answerList == null || answerList.isEmpty()) {
            aiModelLogger.warn("答案列表为空，返回空结果");
            return List.of();
        }
        if (brandList == null || brandList.isEmpty()) {
            aiModelLogger.warn("品牌列表为空，返回未知结果");
            return answerList.stream().map(answer -> "未知").toList();
        }

        long startTime = System.currentTimeMillis();
        String promptText = buildBrandAnalysisPrompt(answerList, brandList);

        try {
            return callBrandAnalysisWithRetry(answerList, brandList, promptText, startTime);
        } catch (Exception e) {
            aiModelLogger.error("品牌分析最终失败 - 耗时: {}ms, 答案数量: {}, 品牌数量: {}, 错误: {}",
                    System.currentTimeMillis() - startTime, answerList.size(), brandList.size(), e.getMessage(), e);
            // 返回默认结果，避免整个流程失败
            return answerList.stream().map(answer -> "未知").toList();
        }
    }

    /**
     * 构建品牌分析提示词
     */
    private String buildBrandAnalysisPrompt(List<String> answerList, List<String> brandList) {
        StringBuilder text = new StringBuilder();
        text.append("请你分析以下两个列表的归属关系：\n");
        text.append("第一个列表为待分析的品牌列表：").append(answerList).append("\n");
        text.append("第二个列表为所属品牌参考列表：").append(brandList).append("\n");
        text.append("请针对第一个列表中的每个品牌，判断其是否包含第二个列表中任意品牌的名称（中文或英文）或英文名（品牌官方命名）\n");
        text.append("若包含：返回对应的所属品牌（需与第二个列表中的品牌名称/英文名完全一致，优先匹配中文官方命名，其次英文官方命名）\n");
        text.append("若不属于任何一个则返回固定词：未知  \n");
        text.append("输出要求：请严格按照第一个列表的顺序，依次给出分析结果，每个结果一行");
        return text.toString();
    }

    /**
     * 带重试机制的品牌分析调用
     */
    private List<String> callBrandAnalysisWithRetry(List<String> answerList, List<String> brandList, String promptText, long startTime) {
        int maxRetries = 2; // 品牌分析重试次数较少
        Exception lastException = null;
        List<String> result = null;

        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                aiModelLogger.debug("第{}次尝试品牌分析 - 答案数量: {}, 品牌数量: {}", attempt, answerList.size(), brandList.size());

                // 尝试使用 entity 方法
//                result = tryBrandAnalysisEntity(promptText, startTime);
//                if (result != null && !result.isEmpty() && result.size() == answerList.size()) {
//                    aiModelLogger.debug("品牌分析Entity方法成功 - 耗时: {}ms, 结果数量: {}",
//                            System.currentTimeMillis() - startTime, result.size());
//                    return result;
//                }

                // 尝试使用 content 方法 + 手动解析
                result = tryBrandAnalysisContent(promptText, answerList.size(), startTime);
                if (result != null && !result.isEmpty() && result.size() == answerList.size()) {
                    return result;
                }
            } catch (Exception e) {
                lastException = e;
                aiModelLogger.warn("第{}次品牌分析尝试失败 - 错误: {}", attempt, e.getMessage());
                // 尝试使用 content 方法 + 手动解析
//                result = tryBrandAnalysisContent(promptText, answerList.size(), startTime);
//                if (result != null && !result.isEmpty()) {
//                    aiModelLogger.debug("品牌分析Content方法成功 - 耗时: {}ms, 结果数量: {}",
//                            System.currentTimeMillis() - startTime, result.size());
//                    return result;
//                }
            }
        }
        // 所有重试都失败，返回默认结果
        if (lastException != null) {
            aiModelLogger.warn("品牌分析重试失败，返回默认结果 - 错误: {}", lastException.getMessage());
        }
        return answerList.stream().map(answer -> "未知").toList();
    }

    /**
     * 尝试使用 entity 方法进行品牌分析
     */
    private List<String> tryBrandAnalysisEntity(String promptText, long startTime) {
        try {

            ChatClient chatClient = brandExposureAiChatClient.getChatClient(ModelChatClientEnum.QWEN.getSource());
            AiCallData callData = chatClient.prompt()
                    .user(promptText)
                    .options(DashScopeChatOptions.builder()
                            .withTemperature(0.2)
                            .build())
                    .call()
                    .entity(AiCallData.class);

            List<String> contents = callData.getContents();
            if (contents != null && !contents.isEmpty()) {
                return contents.stream()
                        .filter(Objects::nonNull)
                        .map(String::trim)
                        .filter(content -> !content.isEmpty())
                        .toList();
            }
        } catch (Exception e) {
            aiModelLogger.debug("品牌分析Entity方法失败 - 错误: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 尝试使用 content 方法进行品牌分析
     */
    private List<String> tryBrandAnalysisContent(String promptText, int expectedSize, long startTime) {
        try {
            ChatClient chatClient = brandExposureAiChatClient.getChatClient(ModelChatClientEnum.QWEN.getSource());
            ChatResponse chatResponse = chatClient.prompt()
                    .user(promptText)
                    .options(DashScopeChatOptions.builder()
                            .withTemperature(0.2)
                            .build())
                    .call()
                    .chatResponse();

            if (chatResponse != null) {
                String content = chatResponse.getResult().getOutput().getText();
                System.err.println("qwen消耗token:" + chatResponse.getMetadata().getUsage().getTotalTokens());
                List<String> parsed = ParseTextUtils.brandAnalysis(content);
                if (parsed.size() == expectedSize) {
                    return parsed;
                }
            }
        } catch (Exception e) {
            aiModelLogger.debug("品牌分析Content方法失败 - 错误: {}", e.getMessage());
        }
        return null;
    }


    /**
     * 调用单个AI模型
     */
    private String callSingleModel(String modelSource, String ownProductName, String competitorNames, String question) {
        StringBuilder text = new StringBuilder();
        text.append("问题：").append(question).append(";");
        text.append("品牌列表：");

        try {
            aiModelLogger.debug("开始调用AI模型 - 模型: {}, 问题: {}", modelSource, question);
            ChatClient chatClient = brandExposureAiChatClient.getChatClient(modelSource);
            String answer = chatClient.prompt()
                    .user(text.toString())
                    .call()
                    .content();
            aiModelLogger.debug("AI模型调用完成 - 模型: {}, 问题: {}, 答案长度: {}",
                    modelSource, text, answer != null ? answer.length() : 0);
            return answer;
        } catch (Exception e) {
            aiModelLogger.error("调用AI模型失败 - 模型: {}, 问题: {}, 错误: {}",
                    modelSource, text, e.getMessage(), e);
            throw new RuntimeException("调用模型 " + modelSource + " 失败: " + e.getMessage(), e);
        }
    }

    /**
     * 分析曝光量
     */
    private BrandExposureResponse analyzeExposure(String ownProductName, List<String> competitors,
                                                  List<String> questions, Map<String, Map<String, BrandExposureAiCallDTO>> modelAnswers,
                                                  List<String> aiModels) {

        // 统计自己的产品在各模型中的曝光次数
        Map<String, Integer> ownProductModelCount = new HashMap<>();
        Map<String, Map<String, Integer>> ownProductQuestionCount = new HashMap<>();
        // 统计竞品在各模型中的曝光次数
        Map<String, Integer> competitorModelCount = new HashMap<>();

        // 初始化计数
        for (String model : aiModels) {
            ownProductModelCount.put(model, 0);
        }

        // 分析每个问题的答案
        for (String question : questions) {
            Map<String, BrandExposureAiCallDTO> answers = modelAnswers.get(question);
            if (answers == null) continue;

            ownProductQuestionCount.put(question, new HashMap<>());

            for (String model : aiModels) {
                BrandExposureAiCallDTO answer = answers.get(model);
                if (answer == null || answer.getAnswerList() == null || answer.getAnswerList().isEmpty()) continue;

                // 检查是否包含自己的产品名称
                if (containsBrandName(answer.getBrandList(), ownProductName)) {
                    ownProductModelCount.put(model, ownProductModelCount.get(model) + 1);
                    ownProductQuestionCount.get(question).put(model, 1);
                } else {
                    ownProductQuestionCount.get(question).put(model, 0);
                }

                // 检查是否包含竞品名称
                if (competitors != null && !competitors.isEmpty()) {
                    for (String competitor : competitors) {
                        if (containsBrandName(answer.getBrandList(), competitor)) {
                            competitorModelCount.put(competitor, (competitorModelCount.get(competitor) == null ? 0 : competitorModelCount.get(competitor)) + 1);
                        }
                    }
                }
            }
        }

        // 构建响应数据
        List<BrandExposureResponse.ModelExposureCount> ownProductExposure = buildModelExposureCount(ownProductModelCount);
        List<BrandExposureResponse.CompetitorComparison> competitorComparison = buildCompetitorComparison(ownProductModelCount, competitorModelCount, ownProductName, competitors);
        List<BrandExposureResponse.QuestionRankingDetail> ownProductRankingList = buildQuestionRankingList(ownProductName, modelAnswers, aiModels);
        List<BrandExposureResponse.QuestionExposureDetail> ownProductDetailedExposure = buildDetailedExposure(ownProductQuestionCount, modelAnswers);
        return new BrandExposureResponse(ownProductExposure, ownProductDetailedExposure, competitorComparison, ownProductRankingList);
    }

    /**
     * 检查答案中是否包含品牌名称
     */
    private boolean containsBrandName(String answer, String brandName) {
        if (answer == null || brandName == null) {
            return false;
        }
        return answer.trim().toLowerCase().contains(brandName.trim().toLowerCase());
    }


    /**
     * 检查答案中是否包含品牌名称
     */
    private boolean containsBrandName(List<String> answers, String brandName) {
        if (answers == null || answers.isEmpty() || brandName == null) {
            return false;
        }
        for (String answer : answers) {
            if (answer.trim().toLowerCase().contains(brandName.trim().toLowerCase())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 构建模型曝光次数统计
     */
    private List<BrandExposureResponse.ModelExposureCount> buildModelExposureCount(Map<String, Integer> modelCount) {
        return modelCount.entrySet().stream()
                .map(entry -> new BrandExposureResponse.ModelExposureCount(
                        entry.getKey(),
                        String.valueOf(entry.getValue()), null
                ))
                .toList();
    }

    /**
     * 构建详细曝光统计
     */
    private List<BrandExposureResponse.QuestionExposureDetail> buildDetailedExposure(
            Map<String, Map<String, Integer>> questionCount, Map<String, Map<String, BrandExposureAiCallDTO>> modelAnswers) {

        return questionCount.entrySet().stream()
                .map(entry -> {
                    String question = entry.getKey();
                    List<BrandExposureResponse.ModelExposureCount> exposureCounts =
                            entry.getValue().entrySet().stream()
                                    .map(countEntry -> new BrandExposureResponse.ModelExposureCount(
                                            countEntry.getKey(),
                                            String.valueOf(countEntry.getValue()),
                                            modelAnswers.get(question) != null && modelAnswers.get(question).get(countEntry.getKey()) != null ? modelAnswers.get(question).get(countEntry.getKey()) : new BrandExposureAiCallDTO()
                                    ))
                                    .toList();

                    return new BrandExposureResponse.QuestionExposureDetail(question, exposureCounts);
                })
                .toList();
    }

    /**
     * 构建竞品对比分析
     */
    private List<BrandExposureResponse.CompetitorComparison> buildCompetitorComparison(
            Map<String, Integer> ownProductCount, Map<String, Integer> competitorCount,
            String ownProductName, List<String> competitors) {

        return Optional.ofNullable(competitors)
                .filter(list -> !list.isEmpty())
                .map(competitorList -> {
                    int ownProductTotal = ownProductCount.values().stream()
                            .mapToInt(Integer::intValue)
                            .sum();

                    return competitorList.stream()
                            .map(competitor -> new BrandExposureResponse.CompetitorComparison(
                                    ownProductName,
                                    ownProductTotal,
                                    competitor,
                                    competitorCount.getOrDefault(competitor, 0)
                            ))
                            .toList();
                })
                .orElse(List.of());
    }


    /**
     * 构建品牌排名列表
     */
    private List<BrandExposureResponse.QuestionRankingDetail> buildQuestionRankingList(
            String ownProductName,
            Map<String, Map<String, BrandExposureAiCallDTO>> modelAnswers,
            List<String> aiModels) {

        return modelAnswers.entrySet().stream()
                .map(questionEntry -> {
                    String question = questionEntry.getKey();
                    Map<String, BrandExposureAiCallDTO> answersPerModel = questionEntry.getValue();

                    List<BrandExposureResponse.RankingDetail> rankingDetails = aiModels.stream()
                            .map(model -> new BrandExposureResponse.RankingDetail(
                                    model,
                                    findBrandRanking(ownProductName, answersPerModel.get(model))
                            ))
                            .toList();

                    return new BrandExposureResponse.QuestionRankingDetail(question, rankingDetails);
                })
                .toList();
    }

    /**
     * 在品牌列表中查找指定品牌的排名
     */
    private Integer findBrandRanking(String ownProductName, BrandExposureAiCallDTO aiCallDTO) {
        return Optional.ofNullable(aiCallDTO)
                .map(BrandExposureAiCallDTO::getBrandList)
                .filter(brandList -> !brandList.isEmpty())
                .flatMap(brandList -> findBrandIndex(brandList, ownProductName))
                .map(index -> index + 1)
                .orElse(0);
    }

    /**
     * 在品牌列表中查找品牌的索引位置
     */
    private Optional<Integer> findBrandIndex(List<String> brandList, String ownProductName) {
        for (int i = 0; i < brandList.size(); i++) {
            if (containsBrandName(brandList.get(i), ownProductName)) {
                return Optional.of(i);
            }
        }
        return Optional.empty();
    }

    /**
     * Java 17优雅关闭线程池
     */
    @PreDestroy
    public void shutdown() {
        logger.info("正在关闭Java 17优化线程池...");
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                logger.warn("线程池未能在60秒内优雅关闭，强制关闭");
                executorService.shutdownNow();
                if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    logger.error("线程池无法正常关闭");
                }
            }
        } catch (InterruptedException e) {
            logger.warn("线程池关闭被中断，强制关闭");
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
        logger.info("Java 17优化线程池已关闭");
    }


}
